/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.meta.service.impl;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.google.common.base.Strings;
import com.je.common.base.DynaBean;
import com.je.common.base.mapper.query.NativeQuery;
import com.je.common.base.service.CommonService;
import com.je.common.base.service.MetaResourceService;
import com.je.common.base.service.rpc.BeanService;
import com.je.common.base.util.DateUtils;
import com.je.common.base.util.StringUtil;
import com.je.meta.model.ExcelParamVo;
import com.je.meta.model.ExcelParameterVo;
import com.je.meta.model.ExcelReturnVo;
import com.je.meta.service.ExcelAssistService;
import com.je.meta.service.GroupImporExceltExecutionService;
import com.je.meta.service.SheetImporExceltExecutionService;
import com.je.meta.service.WayImportExcelHandleDataService;
import com.je.meta.util.commonUtils.CommonUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.*;
import java.util.regex.Pattern;

@Service
public class GroupImporExceltExecutionServiceImpl implements GroupImporExceltExecutionService {

    @Autowired
    private WayImportExcelHandleDataService wayImportExcelHandleDataService;

    @Autowired
    private SheetImporExceltExecutionService sheetImporExceltExecutionService;

    @Autowired
    private MetaResourceService metaResourceService;

    @Autowired
    private ExcelAssistService excelAssistService;

    @Autowired
    private CommonService commonService;

    @Override
    public ExcelReturnVo executeDataPre(Map<String, Object> ddMap, ExcelParameterVo excelParamVo) {
        /**
         * 1.获取执行类型：sql、bean
         * 2.处理所有excel数据
         */
        DynaBean dynaBean  =excelParamVo.getGroup();
        ExcelReturnVo excelReturnVo = null;
        String beforeType  =dynaBean.getStr("BEFORE_TYPE");
        String beforeSql =dynaBean.getStr("BEFORE_SQL");
        if("SQL".equals(beforeType)){
            excelReturnVo = wayImportExcelHandleDataService.handleDataBySql(beforeSql,ddMap);
        }
        if("BEAN".equals(beforeType)){
            excelReturnVo =  wayImportExcelHandleDataService.handleDataByBean(dynaBean.getStr("BEFORE_BEAN"),dynaBean.getStr("BEFORE_METHOD"),null);
        }
        return excelReturnVo;
    }

    @Override
    public void executeData(DynaBean group, String groupTemId, Map<String, Object> ddMap, Map<String,List<Map<Integer,Object>>> excelData, List<DynaBean> sheets, HttpServletRequest request, JSONObject returnObj) {
        /**
         * 1.需判断是否是系统处理
         * 2.需判断是否为预处理
         * 若是预处理，数据进临时表，并将数据返回
         */
        //处理方式
        if (StringUtil.isNotEmpty(groupTemId)) {
            returnObj.put("groupTemId", groupTemId);
        }
        String dataPreview = group.getStr("EXCELGROUP_PRVIEW");
        if("1".equals(dataPreview)){
            NativeQuery nativeQuery = NativeQuery.build().eq("JE_CORE_EXCELGROUP_ID",group.getStr("JE_CORE_EXCELGROUP_ID"));
            if(StringUtil.isNotEmpty(groupTemId)){
                nativeQuery.ne("JE_EXCEL_GROUPTEM_ID",groupTemId);
            }
            metaResourceService.deleteByTableCodeAndNativeQuery("JE_EXCEL_GROUPTEM",nativeQuery);
        }
        JSONArray previewSheetInfo = new JSONArray();
        String dataType = group.getStr("DATA_TYPE");
        List<Map<String,Object>> resultList = new ArrayList<>();
        for(int i =0;i<sheets.size();i++){
            DynaBean sheetItem = sheets.get(i);
            sheetItem.setStr("dataPreview",dataPreview);
            int SY_ORDERINDEX = sheetItem.getInt("SY_ORDERINDEX");
            String excelIndex = String.valueOf(SY_ORDERINDEX-1);

            List<Map<Integer,Object>> nowSheetData = excelData.get(excelIndex);

            List<DynaBean> fields =metaResourceService.selectByTableCodeAndNativeQuery("JE_CORE_EXCELFIELD",
                    NativeQuery.build().eq("JE_CORE_EXCELSHEET_ID",sheetItem.getStr("JE_CORE_EXCELSHEET_ID")).orderByAsc("SY_ORDERINDEX"));

            DynaBean defaultValues = new DynaBean();
            String funcCode = sheetItem.getStr("FUNCCODE");
            String defaultFuncVal = sheetItem.getStr("DATA_DEFAULTVALUE");
            if ("1".equals(defaultFuncVal)) {
                commonService.buildFuncDefaultValues(funcCode, defaultValues);
            }
            String defaultCreateInfo = sheetItem.getStr("DATA_CREATEINFO");
            String tableCode = sheetItem.getStr("TABLECODE");

            //科学计数
            List<String> kxjsFields=new ArrayList<String>();
            //日期
            List<String> dateFields=new ArrayList<String>();
            //日期时间
            List<String> dateTimeFields=new ArrayList<String>();
            //所占行 A-Z
            Map<String, DynaBean> fieldInfos = new HashMap<String, DynaBean>();
            //处理后的数据
            List<DynaBean> datas = new ArrayList<DynaBean>();
            //自动带值数据集
            Map<String, List<DynaBean>> dzValues = new HashMap<String, List<DynaBean>>();
            //带值字段集合
            List<String> dzFields = new ArrayList<String>();
            //以code为key的数据集合
            Map<String, DynaBean> fieldCodeInfos = new HashMap<String, DynaBean>();
            for(DynaBean field:fields){
                String fieldCode = field.getStr("EXCELFIELD_CODE");
                String defaultValue = field.getStr("EXCELFIELD_VALUE");
                String EXCELFIELD_COLUMN = field.getStr("EXCELFIELD_COLUMN");
                String EXCELFIELD_XTYPE = field.getStr("EXCELFIELD_XTYPE");
                fieldCodeInfos.put(field.getStr("EXCELFIELD_CODE"), field);

                if (StringUtil.isNotEmpty(EXCELFIELD_COLUMN)) {
                    fieldInfos.put(EXCELFIELD_COLUMN, field);
                }
                //特殊字段类型
                if("datefield".equals(EXCELFIELD_XTYPE)){
                    dateFields.add(fieldCode);
                }
                if("datetimefield".equals(EXCELFIELD_XTYPE)){
                    dateTimeFields.add(fieldCode);
                }
                //带值配置
                excelAssistService.parseAllDzValues(field, ddMap, dzValues, dzFields, CommonUtils.getRequestParams(request));

                //处理默认值
                if(StringUtil.isNotEmpty(defaultValue)&&(defaultValue.startsWith("@")&&defaultValue.endsWith("@"))){
                    defaultValue="{"+defaultValue+"}";
                }
                if(StringUtil.isNotEmpty(defaultValue)){
                    defaultValues.set(fieldCode,defaultValue);
                }

                //去除科学计数
                if("1".equals(field.getStr("EXCELFIELD_QCKXJS"))){
                    kxjsFields.add(fieldCode);
                }
                //主子
            }
            //将excel数据转为DynaBean
            for(int j =0;j<nowSheetData.size();j++){
                DynaBean dynaBean = new DynaBean();
                if ("1".equals(defaultFuncVal)) {
                    dynaBean.setValues(defaultValues.clone().getValues());
                }
                if ("1".equals(defaultCreateInfo)) {
                    commonService.buildModelCreateInfo(dynaBean);
                }
                if (StringUtil.isNotEmpty(tableCode)) {
                    dynaBean.set(BeanService.KEY_TABLE_CODE, tableCode);
                }
                Map<Integer,Object> excelItemMap = nowSheetData.get(j);
                for (Map.Entry<Integer, Object> entry : excelItemMap.entrySet()) {
                    String nowName = getExcelColumnName(entry.getKey());
                    if(fieldInfos.containsKey(nowName)){
                        DynaBean field = fieldInfos.get(nowName);
                        Object excelValue = entry.getValue();
                        if(!Objects.isNull(excelValue) && !Strings.isNullOrEmpty(excelValue.toString())){
                            dynaBean.set(field.getStr("EXCELFIELD_CODE"),excelValue);
                        }
                    }
                }
                //处理带值
                for (String dzField : dzFields) {
                    DynaBean fieldInfo = fieldCodeInfos.get(dzField);
                    excelAssistService.doSetBeanDzValue(fieldInfo, dynaBean, dzValues, ddMap);
                }
                //处理科学计数
                for(String kejs:kxjsFields){
                    String val = dynaBean.getStr(kejs);
                    if (StringUtil.isNotEmpty(val)) {
                        String regx = "^((-?\\d+.?\\d*)[Ee]{1}(-?\\d+))$";
                        Pattern pattern = Pattern.compile(regx);
                        if (pattern.matcher(val).matches()) {
                            BigDecimal b = new BigDecimal(val);
                            val = b.toPlainString();
                        }
                    }
                    dynaBean.set(kejs, val);
                }
                //处理日期
                for (String dateField : dateFields) {
                    String dateValue = dynaBean.getStr(dateField);
                    if (!Strings.isNullOrEmpty(dateValue)) {
                        try {
                            dynaBean.setStr(dateField, DateUtils.formatDate(DateUtils.getDate(dateValue)));
                        } catch (Exception e) {
                            throw new RuntimeException("日期格式错误");
                        }
                    }
                }
                //处理日期时间
                for (String dateTimeField : dateTimeFields) {
                    String dateValue = dynaBean.getStr(dateTimeField);
                    if (!Strings.isNullOrEmpty(dateValue)) {
                        try {
                            dynaBean.setStr(dateTimeField, DateUtils.formatDateTime(DateUtils.getDate(dateValue)));
                        } catch (Exception e) {
                            throw new RuntimeException("日期格式错误");
                        }
                    }
                }
                dynaBean.set("__CODE__", "1");
                dynaBean.set("__MSG__", "正确");
                datas.add(dynaBean);
            }
            Map<String,Object> result = new HashMap<>();
            //处理后的数据
            List<DynaBean> sheetDatas =datas;
            if("BEAN".equals(dataType)){
                Map<String , List<DynaBean>> map = new HashMap<>();
                map.put(String.valueOf(SY_ORDERINDEX),datas);
                ExcelReturnVo excelReturnVo =  wayImportExcelHandleDataService.handleDataByBean(group.getStr("DATA_BEAN"),group.getStr("DATA_METHOD"),
                        null);
                resultList.add(buildResult(excelReturnVo));
                sheetDatas = excelReturnVo.getSheetValues();
            }else{
                //是否有前后逻辑
                String qhlj = sheetItem.getStr("EXCELSHEET_QHLJ");
                ExcelReturnVo excelSheetReturnVo=null;
                /*if("1".equals(qhlj)){
                    excelSheetReturnVo=  sheetImporExceltExecutionService.executeDataPre(sheetItem,ddMap,new ExcelParamVo(request,null,datas,null,null,"SHEET_BEFORE",null));
                    if("BEAN".equals(sheetItem.getStr("BEFORE_TYPE"))){
                        sheetDatas =excelSheetReturnVo.getSheetValues();
                    }
                }*/
                sheetDatas = sheetImporExceltExecutionService.executeData(group,sheetItem,groupTemId,ddMap,sheetDatas,request,result);
                /*if("1".equals(qhlj)){
                    excelSheetReturnVo =  sheetImporExceltExecutionService.executeDataAfter(ddMap,null);
                    if("BEAN".equals(sheetItem.getStr("BEFORE_TYPE"))){
                        sheetDatas =excelSheetReturnVo.getSheetValues();
                    }
                }*/
                resultList.add(result);
            }
            //如果是预处理则保存数据到临时表
            if("1".equals(dataPreview)){
                excelAssistService.temporarySaveData(group,  sheetItem, sheetDatas,  fields,  groupTemId);
            }
        }
        if ("1".equals(dataPreview)) {
            returnObj.put("PREVIEW", "1");
            returnObj.put("SHEETINFO", previewSheetInfo);
        } else {
            returnObj.put("PREVIEW", "0");
        }
        returnObj.put("result",resultList);
    }

    @Override
    public ExcelReturnVo executeDataAfter(Map<String, Object> ddMap, ExcelParameterVo excelParamVo) {
        /**
         * 1.获取执行类型：sql、bean
         * 2.处理所有excel数据
         */
        DynaBean dynaBean = excelParamVo.getGroup();
        ExcelReturnVo excelReturnVo = null;
        String beforeType  =dynaBean.getStr("BEFORE_TYPE");
        String beforeSql =dynaBean.getStr("BEFORE_SQL");
        if("SQL".equals(beforeType)){
            wayImportExcelHandleDataService.handleDataBySql(beforeSql,ddMap);
        }
        /**
         * 不支持
         */
        /*if("BEAN".equals(beforeType)){
            excelReturnVo =  wayImportExcelHandleDataService.handleDataByBean(dynaBean.getStr("BEFORE_BEAN"),dynaBean.getStr("BEFORE_METHOD"),excelParamVo);
        }*/
        return excelReturnVo;
    }

    private String getExcelColumnName(int i) {
        StringBuilder str = new StringBuilder(2);
        setExcelColumnName(str, i);
        return str.toString();
    }

    private void setExcelColumnName(StringBuilder str, int col) {
        int tmp = col / 26;
        if (tmp > 26) {
            setExcelColumnName(str, tmp - 1);
        } else if (tmp > 0) {
            str.append((char) (tmp + 64));
        }
        str.append((char) (col % 26 + 65));
    }
}
